#include <iostream>
#include <time.h>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/msg.h>
using namespace std;

#define GET_MSG (IPC_CREAT | IPC_EXCL | 0666)
#define USE_MSG IPC_CREAT
const string pathname = ".";
const int proj_id = 0x66;
long CLIENT = 1;
long SERVER = 2;

class Messagequeue
{
    struct msg_t
    {
        long _mtype;
        char _mtext[1024];
    };

public:
    Messagequeue()
    {
    }
    void Create(int flag)
    {
        key_t k = ftok(pathname.c_str(), proj_id);
        if (k < 0)
        {
            cout << "ftok fail" << endl;
            exit(1);
        }
        cout << "ftok success" << endl;

        _msgid = msgget(k, flag);
        if (_msgid < 0)
        {
            cout << "msgget fail" << endl;
            exit(2);
        }
        cout << "msgget success" << endl;
    }
    void Recv(string &in, long &type)
    {
        msg_t msg;
        int n = msgrcv(_msgid, &msg, sizeof(msg._mtext), type, 0);
        if (n < 0)
        {
            cout << "fail msgrcv" << endl;
            exit(5);
        }
        cout << "msgrcv success" << endl;
        msg._mtext[n] = '\0';
        in = msg._mtext;
        cout << "recev Mes:" << in << endl;
    }
    void Send(const string &out, long &type)
    {
        //sleep(5);
        msg_t msg;
        memset(msg._mtext, 0, sizeof(msg._mtext));
        msg._mtype = type;
        memcpy(msg._mtext, out.c_str(), out.size());
        int n = msgsnd(_msgid, &msg, out.size(), 0);
        if (n < 0)
        {
            cout << "msgsnd fail" << endl;
            exit(4);
        }
        cout << "msgsnd success" << endl;
    }
    void Destroy()
    {
        int n = msgctl(_msgid, IPC_RMID, nullptr);
        if (n < 0)
        {
            cout << "msgctl fail" << endl;
            exit(3);
        }
        cout << "msgctl remove" << endl;
    }
    ~Messagequeue()
    {
    }

private:
    int _msgid;
};

class Client : public Messagequeue
{
public:
    Client()
    {
        Messagequeue::Create(USE_MSG);
    }
};

class Server : public Messagequeue
{
public:
    Server()
    {
        Messagequeue::Create(GET_MSG);
    }
    ~Server()
    {
        Messagequeue::Destroy();
    }
};